package eu.codearte.resteeth.config; import eu.codearte.resteeth.annotation.RestClient; import eu.codearte.resteeth.core.BeanProxyCreator; import eu.codearte.resteeth.handlers.RestInvocationHandler; import eu.codearte.resteeth.util.SpringUtils; import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.BeanFactoryAware; import org.springframework.beans.factory.config.BeanDefinitionHolder; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.config.DependencyDescriptor; import org.springframework.beans.factory.support.AutowireCandidateResolver; import org.springframework.core.annotation.AnnotationAttributes; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.StringHttpMessageConverter; import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; import org.springframework.web.client.RestTemplate; import java.lang.annotation.Annotation; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; /** * @author Jakub Kubrynski */ class ResteethAutowireCandidateResolverDelegate implements AutowireCandidateResolver, BeanFactoryAware { private static final String RESTEETH_REST_TEMPLATE_BEAN_NAME = "resteethRestTemplate"; private BeanResolver beanResolver = new BeanResolver(); private ConfigurableListableBeanFactory beanFactory; private BeanProxyCreator beanProxyCreator; private final AutowireCandidateResolver autowireCandidateResolver; private final AnnotationAttributes enableResteethAttributes; private boolean initialized = false; public ResteethAutowireCandidateResolverDelegate(AutowireCandidateResolver autowireCandidateResolver, AnnotationAttributes enableResteethAttributes) { this.autowireCandidateResolver = autowireCandidateResolver; this.enableResteethAttributes = enableResteethAttributes; } @Override public boolean isAutowireCandidate(BeanDefinitionHolder bdHolder, DependencyDescriptor descriptor) { return autowireCandidateResolver.isAutowireCandidate(bdHolder, descriptor); } @Override public Object getSuggestedValue(DependencyDescriptor descriptor) { return autowireCandidateResolver.getSuggestedValue(descriptor); } @Override public Object getLazyResolutionProxyIfNecessary(DependencyDescriptor descriptor, String beanName) { RestClient restClientAnnotation = getRestClientAnnotation(descriptor.getAnnotations()); if (restClientAnnotation != null) { ensueBeanProxyCreatorInitialized(); return beanProxyCreator.createProxyBean(descriptor.getDependencyType(), beanResolver.findEndpointProvider(descriptor.getDependencyType(), beanFactory, restClientAnnotation), enableResteethAttributes, Arrays.asList(descriptor.getAnnotations())); } return autowireCandidateResolver.getLazyResolutionProxyIfNecessary(descriptor, beanName); } private RestClient getRestClientAnnotation(Annotation[] annotations) { for (Annotation annotation : annotations) { if (RestClient.class.equals(annotation.annotationType())) { return (RestClient) annotation; } } return null; } private synchronized void ensueBeanProxyCreatorInitialized() { if (!initialized) { initialized = true; RestTemplate restTemplate = provideRestTemplate(this.beanFactory); final Collection<RestInvocationHandler> handlers = SpringUtils.getBeansOfType(RestInvocationHandler.class, this.beanFactory); beanProxyCreator = new BeanProxyCreator(restTemplate, handlers); } } private RestTemplate provideRestTemplate(ConfigurableListableBeanFactory configurableListableBeanFactory) { if (beanResolver.beanNotDefinedExplicitly(configurableListableBeanFactory, RestTemplate.class)) { ArrayList<HttpMessageConverter<?>> messageConverters = new ArrayList<>(); messageConverters.add(new StringHttpMessageConverter()); messageConverters.add(new MappingJackson2HttpMessageConverter()); configurableListableBeanFactory.registerSingleton(RESTEETH_REST_TEMPLATE_BEAN_NAME, new RestTemplate(messageConverters)); } return configurableListableBeanFactory.getBean(RestTemplate.class); } @Override public void setBeanFactory(BeanFactory beanFactory) throws BeansException { this.beanFactory = (ConfigurableListableBeanFactory) beanFactory; } }